var crypto = require('crypto');

var DuiBa_APPKey = '4ZUgdYtST9EwcgufPqGJV7NtR4ff';
var DuiBa_Host = 'http://www.duiba.com.cn/';
var DuiBa_Secret = '2ZJaR9MgDV7svFNn67vnteSnjvNk';

/**
 * 此接口为兑吧商城请求预扣除积分接口,我们的逻辑是生成一个预扣订单,然后根据他们的异步支付通知更新订单状态,然后实际扣除用户积分
 * @param req
 * @param res
 */
exports.cost = function(req,res){
    //处理用户的积分消费处理
    var uid = req.query.uid;
    var credits = req.query.credits;
    var appKey = req.query.appKey;
    var timestamp = req.query.timestamp;
    var description = req.query.description;
    var orderNum = req.query.orderNum;
    var type = req.query.type;
    var facePrice = req.query.facePrice;
    var actualPrice = req.query.actualPrice;
    var ip = req.query.ip;
    var waitAudit = req.query.waitAudit;
    var params = req.query.params;
    var sign = req.query.sign;
    //设置相应头
    res.setHeader("Content-Type", "application/json");

    if(!uid){
        res.send(getErrorResponse(credits,'用户ID为空'));
        return;
    }
    if(!orderNum){
        res.send(getErrorResponse(credits,'订单号为空'));
        return;
    }
    if(!appKey || appKey != DuiBa_APPKey){
        res.send(getErrorResponse(credits,"获取APPKey失败,或APPKey不正确"));
        return;
    }
    if(!type){
        res.send(getErrorResponse(credits,"获取兑换类型失败"));
        return;
    }
    if(!actualPrice){
        res.send(getErrorResponse(credits,"获取实际扣除余额失败"));
        return;
    }
    if(!sign){
        res.send(getErrorResponse(credits,"获取签名错误"));
        return;
    }
    var requestTimeStamp = new Date().getTime();
    if(requestTimeStamp - timestamp > 5*60*1000){
        res.send(getErrorResponse(credits,'请求过期'));
        return;
    }
    //签名检验
    req.query.appSecret = DuiBa_Secret;
    var keys = Object.keys(req.query).sort();
    var waitSign = '';
    keys.forEach(function(i){
        if(req.query[i] && i != 'sign'){
            waitSign += _utf_encode(String(req.query[i]));
        }
    });
    if(!waitSign){
        res.send(getErrorResponse(credits,'生产签名失败'));
        return;
    }
    //生成本地签名
    var localSign = crypto.createHash('md5').update(waitSign).digest('hex');
    if(localSign != sign){
        res.send(getErrorResponse(credits,'签名验证失败'));
        return;
    }
    //先查询该订单是否已经生成过了
    Parse.Cloud.useMasterKey();
    var _PYPointsOrderQuery = new Parse.Query("PYPointsOrder");
    _PYPointsOrderQuery.equalTo('orderNum',orderNum);
    _PYPointsOrderQuery.count().then(function(count){
        if(count > 0){
            res.send(getErrorResponse(credits,"该订单号已经存在,不能重复生成"));
            return;
        }
        //若没有该订单号则可以开始生成了
        //一切验证通过,开始进行业务逻辑,先写入积分兑换订单信息
        var _User = new Parse.Query('_User');
        _User.get(uid).then(function(pointerUser){
            var _PYPointsOrder = Parse.Object.extend("PYPointsOrder");
            //获取用户的预扣积分的剩余积分
            var userPointers = pointerUser.get('point');
            var prePointer = userPointers - credits;
            //写入订单信息
            var pointsOrder = new _PYPointsOrder();
            pointsOrder.set('user',pointerUser);
            //描述
            if(description){
                pointsOrder.set('description',description);
            }
            //市场价值
            if(facePrice){
                pointsOrder.set('facePrice',parseInt(facePrice));
            }
            //消费IP
            if(ip){
                pointsOrder.set('ip',ip);
            }
            //其他参数
            if(params){
                pointsOrder.set('params',params);
            }
            //是否需要审核
            if(waitAudit){
                pointsOrder.set('waitAudit',waitAudit);
            }
            //消费类别
            pointsOrder.set('useType',type);
            //订单号
            pointsOrder.set('orderNum',orderNum);
            //实际消费余额
            pointsOrder.set('actualPrice',parseInt(actualPrice));
            //消耗积分
            pointsOrder.set('point',parseInt(credits));
            //设置默认订单成功状态
            pointsOrder.set('status',false);
            //存入数据库
            pointsOrder.save(null,{success:function(order){
                //存入数据库成功,开始插入用户的积分消费记录
                res.send(getErrorResponse(prePointer,'',order.id,'ok'));
            },error:function(err){
                res.send(getErrorResponse(prePointer,"生成预付订单失败"));
            }})
        },function(err){
            res.send(getErrorResponse(credits,"获取用户信息失败"));
        })
    },function(err){
        res.send(getErrorResponse(credits,"查询订单数量失败"));
    });


};

/**
 * 此接口为接收异步通知接口,用来更新订单状态并生成积分消费记录,扣除积分
 * @param req
 * @param res
 */
exports.confirm = function(req,res){
    //处理用户的积分消费处理
    var appKey = req.query.appKey;
    var timestamp = req.query.timestamp;
    var success = req.query.success;
    var errorMessage = req.query.errorMessage;
    var orderNum = req.query.orderNum;
    var bizId = req.query.bizId;
    var sign = req.query.sign;

    var creditsReturn = 0;


    if(!orderNum){
        res.send(getErrorResponse(creditsReturn,'订单号为空'));
        return;
    }
    if(!appKey || appKey != DuiBa_APPKey){
        res.send(getErrorResponse(creditsReturn,"获取APPKey失败,或APPKey不正确"));
        return;
    }
    if(!success){
        res.send(getErrorResponse(creditsReturn,"获取状态失败"));
        return;
    }
    if(success != 'true'){
        res.send(getErrorResponse(creditsReturn,"订单状态错误"));
        return;
    }
    if(!sign){
        res.send(getErrorResponse(creditsReturn,"获取签名错误"));
        return;
    }
    var requestTimeStamp = new Date().getTime();
    if(requestTimeStamp - timestamp > 5*60*1000){
        res.send(getErrorResponse(creditsReturn,'请求过期'));
        return;
    }
    //签名检验
    req.query.appSecret = DuiBa_Secret;
    var keys = Object.keys(req.query).sort();
    var waitSign = '';
    keys.forEach(function(i){
        if(req.query[i] && i != 'sign'){
            waitSign += _utf_encode(String(req.query[i]));
        }
    });
    if(!waitSign){
        res.send(getErrorResponse(creditsReturn,'生产签名失败'));
        return;
    }
    //生成本地签名
    var localSign = crypto.createHash('md5').update(waitSign).digest('hex');
    if(localSign != sign){
        res.send(getErrorResponse(creditsReturn,'签名验证失败'));
        return;
    }

    //根据兑吧订单号查找订单,修改订单并且添加积分记录
    var PYPointsOrder = new Parse.Query('PYPointsOrder');
    PYPointsOrder.equalTo('orderNum',orderNum);
    PYPointsOrder.first().then(function(orderPreChange){
        //如果订单的状态已经变为真了,那么直接返回成功
        if(orderPreChange.get('status') == true){
            res.send('ok');
            return;
        }
        //修改订单状态
        orderPreChange.set('status',true);
        orderPreChange.save(null,{success:function(order){
            //修改订单成功,开始处理积分扣除逻辑
            var pointerUserId = orderPreChange.get('user').id;
            //获取用户
            var _UserQuery = new Parse.Query('_User');
            _UserQuery.get(pointerUserId).then(function(pointerUser){
                var credits = orderPreChange.get('point');
                //一切验证通过,开始进行业务逻辑,先写入积分兑换订单信息
                var _PYPoints = Parse.Object.extend("PYPoints");
                var points = new _PYPoints();
                points.set('user',pointerUser);
                points.set('point',-parseInt(credits));
                points.set('operation','cost');
                points.set('content',"商城兑换");
                points.set('target',order.id);
                points.set('targetClassName','PYPointsOrder');
                points.set("oldPoints",pointerUser.get('point'));
                points.save(null,{success:function(point){
                        //写入成功后,就要去做用户积分的递减
                        Parse.Cloud.useMasterKey();
                        pointerUser.increment('point',-parseInt(credits));
                        pointerUser.save(null,{success:function(user){
                            //所有逻辑操作成功
                            res.send('ok');
                        },error:function(err,error){
                            //回滚需要删除数据和修改订单状态
                            orderPreChange.set('status',false).save();
                            point.destroy();
                            res.send(getErrorResponse(creditsReturn,'扣除用户积分失败'));
                        }})
                },error:function(err){
                    //回滚不保证成功
                    orderPreChange.set('status',false).save();
                    //记录消费记录失败,需要重新修改订单状态
                    res.send(getErrorResponse(creditsReturn,'生成用户积分消费记录失败'));

                }
            })
        },function(err){
                //回滚需要修改订单状态
                orderPreChange.set('status',false).save();
                res.send(getErrorResponse(creditsReturn,"查询订单用户信息失败"));
            });
        },error:function(err,error){
            res.send(getErrorResponse(creditsReturn,"修改订单状态失败"));
        }})
    });


};

exports.autoLogin = function(req,res){
    //免登陆用户接口
    var uid = req.params.uid;
    if(!uid){
        res.send("用户ID不能为空");
    }
    //查询用户的积分
    var query = new Parse.Query('_User');
    query.get(uid).then(function(user){
        var points = user.get('point');
        if(!points){
            points = 0;
        }
        var resUrl = DuiBa_Host + 'autoLogin/autologin?';
        resUrl += 'uid='+uid;
        resUrl += '&credits=' + String(points);
        resUrl += '&appKey=' + DuiBa_APPKey;
        var timestamp = String(new Date().getTime());
        resUrl += '&timestamp=' + timestamp;
        //resUrl += '&redirect=';
        var sign = crypto.createHash('md5').update(DuiBa_APPKey+DuiBa_Secret+String(points)+timestamp+uid).digest('hex');
        resUrl += '&sign=' + sign;
        res.redirect(resUrl);
    },function(err){
        res.send(err);
    })
};

function getErrorResponse(credit,message,bZid,status){
    var newStatus = 'fail';
    if(status == 'ok'){
        newStatus = status;
        return JSON.stringify({status:'ok',errorMessage:'',credits:parseInt(credit),bizId:bZid});
    }
    return JSON.stringify({status:newStatus,errorMessage:message,credits:parseInt(credit)});
}

/**
 * utf编码字符串
 * @param string
 * @returns {string}
 * @private
 */
function _utf_encode(string){
    string = string.replace(/rn/g,"n");
    var utftext ="";
    for (var n = 0; n < string.length; n++){
        var c = string.charCodeAt(n);
        if (c < 128){
            utftext += String.fromCharCode(c);
        }
        else if((c > 127) && (c < 2048)){
            utftext += String.fromCharCode((c >> 6) | 192);
            utftext += String.fromCharCode((c & 63) | 128);
        }
        else{
            utftext += String.fromCharCode((c >> 12) | 224);
            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
            utftext += String.fromCharCode((c & 63) | 128);
        }
    }
    return utftext;
}